﻿using ML.Entity;
using System;
using System.Web.Configuration;
using System.Web.Http;
using ML.Plug;
using Newtonsoft.Json.Linq;
using ML.IBusiness;
using ML.Utils;
using ML.WebApi.Controllers.Utils;
using Senparc.Weixin;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.Helpers;
using Senparc.Weixin.MP.TenPayLibV3;

namespace ML.WebApi.Controllers
{
    /// <summary>
    /// 微信方面的控制器
    /// </summary>
    [CrossSite]
    public class WechatController : BaseApiController
    {
        //初始化微信支付配置
        private static TenPayV3Info _tenPayV3Info;
        private static readonly string AppId = WebConfigurationManager.AppSettings["TenPayV3_AppId"];
        private static readonly string AppSecret = WebConfigurationManager.AppSettings["TenPayV3_AppSecret"];
        private static readonly string PayDir = WebConfigurationManager.AppSettings["TenPayV3_PayDir"];
        private static readonly string CertDir = WebConfigurationManager.AppSettings["TenPayV3_CertDir"];
        private static readonly string MchId = WebConfigurationManager.AppSettings["TenPayV3_MchId"];
        private static readonly string WechatRedirect = WebConfigurationManager.AppSettings["WechatRedirect"];


        public static TenPayV3Info TenPayV3Info
        {
            get
            {
                if (_tenPayV3Info == null)
                {
                    _tenPayV3Info = TenPayV3InfoCollection.Data[MchId];
                }
                return _tenPayV3Info;
            }
        }

        //初始化数据操作配置
        private readonly IUserBusiness userBusiness;
        private readonly IOrderBusiness orderBusiness;
        private readonly ILogger logger = new NLogLogger();
        public WechatController(IUserBusiness userBusiness, IOrderBusiness orderBusiness)
        {
            this.userBusiness = userBusiness;
            this.orderBusiness = orderBusiness;
        }

        /// <summary>
        /// 前台接口已经在使用—用户在这里组装授权地址(响应回调)
        /// </summary>
        /// <returns></returns>
        [Route("api/wechat/authorlogin")]
        [HttpGet]
        public BaseResult<string> AuthorLogin()
        {
            string url = WechatConfig.rerurnUrl;
            return new BaseResult<string>(200, url);
        }

        /// <summary>
        /// 前台接口已经在使用—单击同意后,获取code并且读取用户信息处理业务
        /// </summary>
        /// <param name="code">微信Code</param>
        /// <returns></returns>
        [Route("api/wechat/authorregister")]
        [HttpGet]
        public BaseResult<UserEntity> AuthorRegister(string code)
        {
            try
            {
                //根据传递的Code读取用户信息并且完成所有业务
                JObject userinfo = WechatHelper.OAuth2UserInfo(code);
                UserEntity userEntity = new UserEntity
                {
                    NickName = userinfo["nickname"].ToString(),
                    OpenId = userinfo["openid"].ToString(),
                    PhotoGraph = userinfo["headimgurl"].ToString(),
                    Gender = Convert.ToInt32(userinfo["sex"].ToString()),
                    Country = userinfo["country"].ToString(),
                    City = userinfo["city"].ToString(),
                    Province = userinfo["province"].ToString()
                };

                //处理业务并且返回(如果存在不插入否则插入)
                var data = userBusiness.AddWXUser(userEntity);
                return data;
            }
            catch (Exception ex)
            {
                logger.Info("AuthorRegister is error." + ex.Message);
                return new BaseResult<UserEntity>(data: null, status_code: 201, status_message: "操作失败");
            }
        }

        /// <summary>
        /// 前台接口已经在使用—生成微信公众号支付参数
        /// </summary>
        /// <param name="cartOrder">订单修改实体</param>
        /// <returns></returns>
        [Route("api/wechat/payinfo")]
        [HttpPost]
        public BaseResult<PayResponse> PayInfo(CartOrders cartOrder)
        {
            logger.Info("调用微信支付，传递参数：支付人的Ip地址：" + IpHelper.GetHostAddress() + ",订单Id：" + cartOrder.OrderId + ",支付单OpenId:" + cartOrder.OpenId);

            //首先获取订单信息，查询订单是否存在
            var entity = orderBusiness.GetById(cartOrder.OrderId).data;
            if (entity == null)
            {
                logger.Error("未查询到该订单下的信息，订单号为：" + cartOrder.OrderId);
                return new BaseResult<PayResponse>(3000);
            }

            //调用修改订单的方法修改订单的部分信息
            var isTrue = orderBusiness.Update(entity, cartOrder);

            //调用支付时限
            try
            {
                var timeStamp = TenPayV3Util.GetTimestamp();
                var nonceStr = TenPayV3Util.GetNoncestr();
                var body = $"{entity.Name}-外卖订单";
                var price = entity.ActPayRMB * 100;          //单位：分
                var xmlDataInfo = new TenPayV3UnifiedorderRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, body, cartOrder.OrderId, (int)price,
                    IpHelper.GetHostAddress(), TenPayV3Info.TenPayV3Notify, TenPayV3Type.JSAPI, cartOrder.OpenId, TenPayV3Info.Key, nonceStr);
                //调用统一订单接口
                var result = TenPayV3.Unifiedorder(xmlDataInfo);
                var package = string.Format("prepay_id={0}", result.prepay_id);

                var payResponse = new PayResponse
                {
                    AppId = TenPayV3Info.AppId,
                    TimeStamp = timeStamp,
                    NonceStr = nonceStr,
                    Package = package,
                    PaySign = TenPayV3.GetJsPaySign(TenPayV3Info.AppId, timeStamp, nonceStr, package, TenPayV3Info.Key)
                };
                return new BaseResult<PayResponse>(200, payResponse);
            }
            catch (Exception ex)
            {
                logger.Error("支付失败，失败原因是：" + ex);
                return new BaseResult<PayResponse>(3001);
            }
        }

        /// <summary>
        /// 前台接口已经在使用—检查订单支付是否成功并修改订单状态
        /// </summary>
        /// <param name="orderId">订单id</param>
        /// <param name="weixinOrderId">微信支付id</param>
        /// <returns></returns>
        [HttpGet]
        [Route("api/wechat/checkpaysuccess")]
        public BaseResult<string> CheckPaySuccess(string orderId, string weixinOrderId)
        {
            logger.Info("微信回调，传递的订单Id是：" + orderId + ",微信订单Id:" + weixinOrderId);

            BaseResult<string> data = new BaseResult<string>();
            var result = TenPayV3.OrderQuery(new TenPayV3OrderQueryRequestData(AppId, MchId, weixinOrderId, TenPayV3Util.GetNoncestr(),
                orderId, TenPayV3Info.Key));

            logger.Info("查询微信信息，返回的回调信息是：" + JsonNetHelper.SerializeObject(result));

            if (result.result_code != "SUCCESS")
            {
                data = new BaseResult<string>(3003, "查询失败，请稍后重试");
            }
            switch (result.trade_state)
            {
                case "SUCCESS":
                    data = new BaseResult<string>(200, "支付成功");
                    orderBusiness.UpdatePayState(orderId, 1);
                    break;
                case "REFUND":
                    data = new BaseResult<string>(3004, "转入退款");
                    break;
                case "NOTPAY":
                    data = new BaseResult<string>(3005, "未支付");
                    break;
                case "CLOSED":
                    data = new BaseResult<string>(3006, "已关闭");
                    break;
                case "REVOKED":
                    data = new BaseResult<string>(3007, "已撤销（刷卡支付）");
                    break;
                case "USERPAYING":
                    data = new BaseResult<string>(3008, "用户支付中");
                    break;
                case "PAYERROR":
                    data = new BaseResult<string>(3009, "支付失败");
                    break;
                default:
                    data = new BaseResult<string>(3010, "未知错误");
                    break;
            }
            return data;
        }

        /// <summary>
        /// 支付回调
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("api/wechat/paynotify")]
        public IHttpActionResult PayNotifyUrl()
        {
            try
            {
                ResponseHandler resHandler = new ResponseHandler(null);

                string return_code = resHandler.GetParameter("return_code");
                string return_msg = resHandler.GetParameter("return_msg");

                string res = null;

                resHandler.SetKey(TenPayV3Info.Key);
                //验证请求是否从微信发过来（安全）
                if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS")
                {
                    res = "success";//正确的订单处理
                    //直到这里，才能认为交易真正成功了，可以进行数据库操作，但是别忘了返回规定格式的消息！
                }
                else
                {
                    res = "wrong";//错误的订单处理
                }

                /* 这里可以进行订单处理的逻辑 */

                //发送支付成功的模板消息
                try
                {
                    string appId = WebConfigurationManager.AppSettings["WeixinAppId"];//与微信公众账号后台的AppId设置保持一致，区分大小写。
                    string openId = resHandler.GetParameter("openid");
                    var templateData = new WeixinTemplate_PaySuccess("http://wmapi.52xdz.top", "购买商品", "状态：" + return_code);

                    Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数", appId + " , " + openId);

                    var result = TemplateApi.SendTemplateMessage(appId, openId, templateData);
                }
                catch (Exception ex)
                {
                    Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息", ex.ToString());
                }

                string xml = string.Format(@"<xml>
<return_code><![CDATA[{0}]]></return_code>
<return_msg><![CDATA[{1}]]></return_msg>
</xml>", return_code, return_msg);

                WeixinTrace.SendCustomLog("PayNotifyUrl ok:", xml);
                return Ok(xml);
            }
            catch (Exception ex)
            {
                WeixinTrace.SendCustomLog("PayNotifyUrl", ex.Message);
                throw;
            }
        }

        /// <summary>
        /// 获取jssdk授权信息
        /// </summary>
        /// <param name="url">带授权的url</param>
        /// <returns></returns>
        [HttpGet]
        [Route("api/wechat/jssdkuipackage")]
        public BaseResult<JsSdkUiPackage> GetJsSdkUiPackage(string url)
        {
            BaseResult<JsSdkUiPackage> r = new BaseResult<JsSdkUiPackage>();
            var jssdkUiPackage = JSSDKHelper.GetJsSdkUiPackage(AppId, AppSecret, url);
            r.data = jssdkUiPackage;
            return r;
        }
    }
}